package com.tn.socket;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ClassName ServerConfig
 * @Description 发卡机
 * @Author Yezhongzhu
 * @Date 2021/12/30 10:42
 * @Version v1.0
 **/

@Slf4j
public class CardSendRobot extends Thread{
    //客户端
    private Socket socket;
    //输入流
    private DataInputStream dis = null;
    //输出流
    private DataOutputStream dos = null;
    //连接状态
    private boolean bConnected = false;

    /**
     * 可以用充电宝数
     */
    private int USABLE_BATTERY = 0;

    //发卡机id
    private String STATIONID;

    //发卡机类型 借/还
    private Integer TYPE;
    //放置位置对应的大门闸道
    private String GATE_ID_NO;
    //是否准备就绪
    private boolean isReady;
    //借卡订单对应的卡片id
    private Map<String,String> orderMap = new ConcurrentHashMap<>();
    private Map<String,Boolean> workMap = new ConcurrentHashMap<>();

    /**
     * 初始化对象 有客户端连进来就创建对象以及输入输出流
     * @param socket
     */
    public CardSendRobot(Socket socket) {
        try {
            this.socket = socket;
            dis = new DataInputStream(socket.getInputStream());
            dos = new DataOutputStream(socket.getOutputStream());
            bConnected = true;
            log.info("------------来自客户端:{},已连接",getHostAddress());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 获取spring容器管理的类，可以获取到sevrice的类
    private SocketCommonHandle service = SpringUtil.getBean(SocketCommonHandle.class);

    //连接池
    private SocketPoolRunner poolRunner = SpringUtil.getBean(SocketPoolRunner.class);

    /**
     * 处理客户端发来的报文
     * @param request
     * @return
     * @throws IOException
     */
    private String handle(String request) throws IOException {
        log.info("接受的数据:{}", request);
        String resultMsg = service.handle(request,this);
        log.info("返回的数据：{} ",resultMsg);
        return resultMsg;
    }

    /**
     * 向客户端回执报文
     * @param str
     */
    public void send(String str) {
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new OutputStreamWriter(dos));
            writer.write(str);
            writer.newLine();
            writer.flush();
        } catch (IOException e) {
            log.info("对方退出了！从List里面去掉了！");
            poolRunner.clients.remove(this);
            bConnected = false;
        }
    }

    //发送借卡请求
    public void borrowCard(String str){
        this.setWorkRunStatus(this.STATIONID,false);
        send(str);
    }

    /**
     * 接收报文消息
     */
    @Override
    public void run() {
        try {
            while (bConnected) {
                String str = "";
                try {
                    //不仅仅是起到勺子舀输入流里面数据的作用，也是存储数据
                    byte [] b=new byte[1024];
                    StringBuffer sb=new StringBuffer();
                    int len=0;
                    String s=null;
                    if((len=dis.read(b))!=-1){
                        s=new String(b);
                        sb.append(s);
                    }
                    str = sb.toString();
                } catch (IOException e) {
                    log.info("----客户端:{}, error:{}",getHostAddress(),e.getMessage(),e);
                }
                log.info("----客户端:{}, 来消息:{}" ,getHostAddress(), str);
                String result = handle(str);
                this.send(result);
            }
        } catch (EOFException e) {
            log.info("Client closed!");
        } catch (IOException e) {
            log.info("Client closed!");
        } finally {
            try {
                if (dis != null)
                    dis.close();
                if (dos != null)
                    dos.close();
                if (socket != null) {
                    socket.close();
                }
                poolRunner.clients.remove(this);
                log.info("对方退出了！从List里面去掉了！now client size:{}",poolRunner.clients.size());
                bConnected = false;
            } catch (IOException e1) {
                e1.printStackTrace();
                poolRunner.clients.remove(this);
                log.info("对方退出了！从List里面去掉了！now client size:{}",poolRunner.clients.size());
                bConnected = false;
            }

        }
    }

    /**
     * 获取当前客户端的ip地址
     * @return
     */
    public String getHostAddress(){
        return socket.getInetAddress().getHostAddress();
    }

    public int getUSABLE_BATTERY() {
        return USABLE_BATTERY;
    }

    public void setUSABLE_BATTERY(int USABLE_BATTERY) {
        this.USABLE_BATTERY = USABLE_BATTERY;
    }

    public String getSTATIONID() {
        return STATIONID;
    }
    //插入STATIONID
    public void setSTATIONID(String STATIONID) {
        this.STATIONID = STATIONID;
    }

    public Integer getTYPE() {
        return TYPE;
    }

    public void setTYPE(Integer TYPE) {
        this.TYPE = TYPE;
    }

    //判断是否可借用
    public boolean isBorrowed(){
        if(null!=TYPE&&1==TYPE&&USABLE_BATTERY>0&&isReady){
            return true;
        }
        return false;
    }
    //判断是否归还
    public boolean isReturnBack(){
        if(null!=TYPE&&0==TYPE&&isReady){
            return true;
        }
        return false;
    }

    public String getGATEIDNO() {
        return GATE_ID_NO;
    }

    public void setGATEIDNO(String GATE_ID_NO) {
        this.GATE_ID_NO = GATE_ID_NO;
    }

    public boolean isReady() {
        return isReady;
    }

    public void setReady(boolean ready) {
        isReady = ready;
    }

    // 写入借卡任务ID和借出卡的ID
    public void setOrderMap(String orderId,String cardId){
        orderMap.put(orderId,cardId);
    }
    //获取借用卡id
    public String getBorrowCardId(String orderId){
        return orderMap.get(orderId);
    }
    //删除借用卡
    public void removeBorrowOrderId(String orderId){
        orderMap.remove(orderId);
    }


    public void setWorkRunStatus(String orderId,boolean flag){
        workMap.put(orderId,flag);
    }

    public Boolean getWorkRunStatus(String orderId){
        return workMap.get(orderId);
    }
    public void removeWorkResult(String orderId){
        orderMap.remove(orderId);
    }
}
